package obj

// Environment 表示Scheme环境，用于存储变量和过程绑定
type Environment interface {
	// Get 从环境中获取变量或过程的值
	Get(name string) (Object, bool)

	// Set 在环境中设置变量或过程的值
	Set(name string, val Object)

	// NewEnclosedEnvironment 创建一个新的、继承自当前环境的封闭环境
	NewEnclosedEnvironment() Environment
	
	// FindEnvironment finds the environment where a variable is defined
	FindEnvironment(name string) Environment
}

// 内置过程类型定义
type BuiltinFunction func(args []Object, env Environment) Object

// Builtin 表示内置过程对象
type Builtin struct {
	Fn BuiltinFunction
}

// Type 返回对象类型
func (b *Builtin) Type() ObjectType {
	return BUILTIN_OBJ
}

// String 返回内置过程的字符串表示
func (b *Builtin) String() string {
	return "builtin function"
}

// Inspect 返回内置过程的详细表示
func (b *Builtin) Inspect() string {
	return "builtin function"
}

// 定义Builtin对象类型常量
const BUILTIN_OBJ = "BUILTIN"

// gcd calculates the greatest common divisor of two integers

// 具体的环境实现
type SimpleEnvironment struct {
	store map[string]Object
	outer Environment
}

// NewEnvironment 创建一个新的环境
func NewEnvironment() Environment {
	s := make(map[string]Object)
	return &SimpleEnvironment{
		store: s,
		outer: nil,
	}
}

// NewEnclosedEnvironment 创建一个封闭环境
func NewEnclosedEnvironment(outer Environment) Environment {
	env := NewEnvironment()
	env.(*SimpleEnvironment).outer = outer
	return env
}

// Get 从环境中获取变量值
func (e *SimpleEnvironment) Get(name string) (Object, bool) {
	obj, ok := e.store[name]
	if !ok && e.outer != nil {
		obj, ok = e.outer.Get(name)
	}
	return obj, ok
}

// Set 在环境中设置变量值
func (e *SimpleEnvironment) Set(name string, val Object) {
	e.store[name] = val
}

// FindEnvironment finds the environment where a variable is defined
func (e *SimpleEnvironment) FindEnvironment(name string) Environment {
	// Check if variable exists in current environment
	_, ok := e.store[name]
	if ok {
		return e
	}
	
	// If not found and there's an outer environment, check there
	if e.outer != nil {
		return e.outer.FindEnvironment(name)
	}
	
	// Variable not found in any environment
	return nil
}

// NewEnclosedEnvironment 创建一个新的、继承自当前环境的封闭环境
func (e *SimpleEnvironment) NewEnclosedEnvironment() Environment {
	return NewEnclosedEnvironment(e)
}

// 创建全局环境
type GlobalEnvironment struct {
	Environment
}

// NewGlobalEnvironment 创建并初始化全局环境，包含所有内置过程
func NewGlobalEnvironment() *GlobalEnvironment {
	env := NewEnvironment()
	return &GlobalEnvironment{env}
}

// FindEnvironment finds the environment where a variable is defined
func (g *GlobalEnvironment) FindEnvironment(name string) Environment {
	return g.Environment.(*SimpleEnvironment).FindEnvironment(name)
}
